package com.core.cloudcommon.trace;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @author =====Lqj=====
 * @className TraceLogger
 * @description 链路追踪日志记录器
 * @create 2024/12/17 10:30
 **/
@Slf4j
@Component
public class TraceLogger {

    /**
     * 记录信息日志
     * @param message 日志消息
     * @param args 参数
     */
    public static void info(String message, Object... args) {
        // MDC会自动添加链路ID，无需手动添加
        log.info(message, args);
    }

    /**
     * 记录调试日志
     * @param message 日志消息
     * @param args 参数
     */
    public static void debug(String message, Object... args) {
        // MDC会自动添加链路ID，无需手动添加
        log.debug(message, args);
    }

    /**
     * 记录警告日志
     * @param message 日志消息
     * @param args 参数
     */
    public static void warn(String message, Object... args) {
        // MDC会自动添加链路ID，无需手动添加
        log.warn(message, args);
    }

    /**
     * 记录错误日志
     * @param message 日志消息
     * @param args 参数
     */
    public static void error(String message, Object... args) {
        // MDC会自动添加链路ID，无需手动添加
        log.error(message, args);
    }

    /**
     * 记录错误日志（带异常）
     * @param message 日志消息
     * @param throwable 异常
     */
    public static void error(String message, Throwable throwable) {
        // MDC会自动添加链路ID，无需手动添加
        log.error(message, throwable);
    }

    /**
     * 记录业务操作日志
     * @param operation 操作名称
     * @param description 操作描述
     * @param result 操作结果
     */
    public static void business(String operation, String description, Object result) {
        Long userId = TraceContext.getUserId();
        String userName = TraceContext.getUserName();

        // MDC会自动添加链路ID，无需手动添加
        log.info("[Business] 操作: {}, 描述: {}, 用户: {}({}), 结果: {}",
                operation, description, userName, userId, result);
    }

    /**
     * 记录业务操作开始日志
     * @param operation 操作名称
     * @param description 操作描述
     * @param params 操作参数
     */
    public static void businessStart(String operation, String description, Object params) {
        String traceId = TraceContext.getTraceId();
        Long userId = TraceContext.getUserId();
        String userName = TraceContext.getUserName();
        
        log.info("[TraceId:{}] [Business-Start] 操作: {}, 描述: {}, 用户: {}({}), 参数: {}", 
                traceId, operation, description, userName, userId, params);
    }

    /**
     * 记录业务操作结束日志
     * @param operation 操作名称
     * @param description 操作描述
     * @param result 操作结果
     * @param elapsedTime 耗时
     */
    public static void businessEnd(String operation, String description, Object result, Long elapsedTime) {
        String traceId = TraceContext.getTraceId();
        Long userId = TraceContext.getUserId();
        String userName = TraceContext.getUserName();
        
        log.info("[TraceId:{}] [Business-End] 操作: {}, 描述: {}, 用户: {}({}), 结果: {}, 耗时: {}ms", 
                traceId, operation, description, userName, userId, result, elapsedTime);
    }

    /**
     * 记录数据库操作日志
     * @param operation 操作类型（SELECT、INSERT、UPDATE、DELETE）
     * @param table 表名
     * @param condition 条件
     * @param result 结果
     */
    public static void database(String operation, String table, String condition, Object result) {
        String traceId = TraceContext.getTraceId();
        
        log.info("[TraceId:{}] [Database] 操作: {}, 表: {}, 条件: {}, 结果: {}", 
                traceId, operation, table, condition, result);
    }

    /**
     * 记录外部接口调用日志
     * @param service 服务名称
     * @param method 方法名称
     * @param params 参数
     * @param result 结果
     * @param elapsedTime 耗时
     */
    public static void externalCall(String service, String method, Object params, Object result, Long elapsedTime) {
        String traceId = TraceContext.getTraceId();
        
        log.info("[TraceId:{}] [External] 服务: {}, 方法: {}, 参数: {}, 结果: {}, 耗时: {}ms", 
                traceId, service, method, params, result, elapsedTime);
    }

    /**
     * 记录缓存操作日志
     * @param operation 操作类型（GET、SET、DELETE）
     * @param key 缓存键
     * @param value 缓存值
     * @param result 操作结果
     */
    public static void cache(String operation, String key, Object value, Object result) {
        String traceId = TraceContext.getTraceId();
        
        log.info("[TraceId:{}] [Cache] 操作: {}, 键: {}, 值: {}, 结果: {}", 
                traceId, operation, key, value, result);
    }

    /**
     * 记录性能监控日志
     * @param method 方法名称
     * @param elapsedTime 耗时
     * @param params 参数
     */
    public static void performance(String method, Long elapsedTime, Object params) {
        String traceId = TraceContext.getTraceId();
        
        if (elapsedTime > 1000) { // 超过1秒的慢操作
            log.warn("[TraceId:{}] [Performance-Slow] 方法: {}, 耗时: {}ms, 参数: {}", 
                    traceId, method, elapsedTime, params);
        } else {
            log.debug("[TraceId:{}] [Performance] 方法: {}, 耗时: {}ms, 参数: {}", 
                    traceId, method, elapsedTime, params);
        }
    }

    /**
     * 记录安全相关日志
     * @param event 安全事件
     * @param description 描述
     * @param level 级别（INFO、WARN、ERROR）
     */
    public static void security(String event, String description, String level) {
        String traceId = TraceContext.getTraceId();
        Long userId = TraceContext.getUserId();
        String userName = TraceContext.getUserName();
        String clientIp = TraceContext.getClientIp();
        
        String message = String.format("[TraceId:%s] [Security] 事件: %s, 描述: %s, 用户: %s(%s), IP: %s", 
                traceId, event, description, userName, userId, clientIp);
        
        switch (level.toUpperCase()) {
            case "WARN":
                log.warn(message);
                break;
            case "ERROR":
                log.error(message);
                break;
            default:
                log.info(message);
                break;
        }
    }



    /**
     * 获取当前链路追踪信息的格式化字符串
     */
    public static String getCurrentTraceInfo() {
        TraceContext.TraceInfo traceInfo = TraceContext.getCurrentTraceInfo();
        if (traceInfo != null) {
            return String.format("TraceId: %s, User: %s(%s), URI: %s, IP: %s", 
                    traceInfo.getTraceId(), 
                    traceInfo.getUserName(), 
                    traceInfo.getUserId(), 
                    traceInfo.getRequestUri(), 
                    traceInfo.getClientIp());
        }
        return "No trace context";
    }
}
